﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Cards
{
    public class Deck
    {
        private readonly Random _random = new Random();
        private List<Card> _cards;

        public bool IsEmpty { get { return !_cards.Any(); } }

        /// <summary>
        /// Creates a new deck in sorted order.
        /// </summary>
        public Deck()
        {
            _cards = new List<Card>();
            for (var suit = 0; suit <= 3; suit++)
                for (var value = 1; value <= 13; value++)
                    _cards.Add(new Card((CardSuit)suit, (CardRank)value));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns>
        /// IndexOutOfRangeException if there are no more cards left
        /// </returns>
        public Card DealCard()
        {
            if (_cards.Count == 0)
                throw new IndexOutOfRangeException("No more cards left in the deck.");

            var card = _cards.First();
            _cards.RemoveAt(0);

            return card;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cardPosition">Position of the card to retrieve.  0 based</param>
        /// <returns>
        /// IndexOutOfRangeException if the card position is not within the range of cards left
        /// </returns>
        public Card GetCard(int cardPosition)
        {
            if (cardPosition < 0 || cardPosition > _cards.Count)
                throw new IndexOutOfRangeException("Invalid card choice.");

            var card = _cards.ElementAt(cardPosition);
            _cards.RemoveAt(cardPosition);

            return card;
        }


        /// <summary>
        /// Randomizes the deck order
        /// </summary>
        public void Shuffle()
        {
            var newCards = new List<Card>();
            while (_cards.Count > 0)
            {
                var cardToMove = _random.Next(_cards.Count);
                newCards.Add(_cards[cardToMove]);
                _cards.RemoveAt(cardToMove);
            }
            _cards = newCards;
        }

        /// <summary>
        /// Returns the count of how many cards are left in the deck
        /// </summary>
        public int Count { get { return _cards.Count; } }
    }
}